package org.client.otdr.executor;

import java.util.Arrays;

import org.client.otdr.EventTableCreator;
import org.client.otdr.Executor;
import org.client.otdr.OTDRID;
import org.client.otdr.Measurer;
import org.client.otdr.MeasurerHandler;
import org.client.otdr.OtdrDevice;
import org.client.otdr.OtdrDomainService;
import org.client.otdr.RemoteMeasurer;
import org.openems.entity.ChoiceEntity;
import org.openems.entity.Key;
import org.openems.entity.NumericEntity;
import org.openems.entity.TableEntity;
import org.openems.entity.TraceEntity;

import framework.Accessor;
import framework.AccessorHelperImpl;
import framework.UtilityUnit;
import framework.webclient.RestSocket;
import framework.webclient.SystemProperty;

public class ControlExecutor implements Executor {

	private Accessor accessor;
	private RestSocket restSocket;
	private SystemProperty systemProperty;
	private Measurer otdrDevice;
	
	public ControlExecutor(Accessor accessor, RestSocket restSocket, SystemProperty systemProperty) {
		this.accessor = accessor;
		this.restSocket = restSocket;
		this.systemProperty = systemProperty;
		otdrDevice = new OtdrDevice();
	}

	@Override
	public void execute(Key key) {
		final OTDRID id = OTDRID.get();
		final ChoiceEntity entity = (ChoiceEntity)accessor.get(id.CONTROL);
		if (entity.getValueText().equals(OtdrDomainService.MEASUREMENT_START)) {
			MeasurerHandler measureHandler = new MeasurerHandler() {
				@Override
				public void onStart() {
					entity.setValueText(OtdrDomainService.MEASUREMENT_START);
					accessor.put(entity);
				}
				
				@Override
				public void onUpdate(Double[] data) {
					TraceEntity traceEntity = (TraceEntity)accessor.get(id.TRACE);
					traceEntity.setData(data);
					traceEntity.setHorizontalMin(0.0);
					Double ior = ((NumericEntity)accessor.get(id.IOR)).getValue();
					ChoiceEntity distance = (ChoiceEntity)accessor.get(id.DISTANCERANGE);
					double dist = UtilityUnit.toDouble(distance.getValueText());
					traceEntity.setHorizontalMax(dist*ior/1.5);
					accessor.put(traceEntity);
										
					NumericEntity activeRange = (NumericEntity)accessor.get(id.ACTIVETRACERANGE);
					activeRange.setValue(dist);
					accessor.put(activeRange);
				}

				@Override
				public void onComplete() {
					entity.setValueText(OtdrDomainService.MEASUREMENT_STOP);
					accessor.put(entity);
					
					new EventTableCreator().create(new AccessorHelperImpl(accessor));
				}
			};
			this.getMeasurer().start(accessor.get(id.WAVELENGTH).getValueText(), accessor.get(id.PULSEWIDTH).getValueText(), measureHandler);
		}
		else {
			this.getMeasurer().stop();
		}
	}
	
	private Measurer getMeasurer() {
		OTDRID id = OTDRID.get();
		if (accessor.get(id.DEVICE).getValueText().equals(OtdrDomainService.DEVICE_LOCAL)) {
			return otdrDevice;
		}
		else {
			return new RemoteMeasurer(restSocket);
		}
	}
}
